#include "cache_manager.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

#pragma pack(push, 1)
typedef struct {
    long long lba;
    char hash[XXH64_HEX_LEN + 1];
} lba_map_entry_t;
#pragma pack(pop)

cache_manager_t* cache_manager_create(const char* disk_cache_dir, const char* lba_map_path) {
    cache_manager_t* cm = (cache_manager_t*)malloc(sizeof(cache_manager_t));
    if (!cm) return NULL;

    cm->disk_cache_dir = strdup(disk_cache_dir);
    cm->lba_map = g_hash_table_new(g_int64_hash, g_int64_equal);

    FILE* fp = fopen(lba_map_path, "rb");
    if (!fp) {
        LOG_ERROR("无法打开 LBA Map 文件: %s", lba_map_path);
        free(cm->disk_cache_dir);
        g_hash_table_destroy(cm->lba_map);
        free(cm);
        return NULL;
    }

    lba_map_entry_t entry;
    while (fread(&entry, sizeof(lba_map_entry_t), 1, fp) == 1) {
        gpointer key = g_new(gint64, 1);
        *(gint64*)key = entry.lba;
        gpointer value = g_strdup(entry.hash);
        g_hash_table_insert(cm->lba_map, key, value);
    }
    fclose(fp);
    LOG_INFO("LBA Map 加载完毕, 共 %u 条目", g_hash_table_size(cm->lba_map));

    return cm;
}

void cache_manager_destroy(cache_manager_t* cm) {
    if (cm) {
        free(cm->disk_cache_dir);
        g_hash_table_destroy(cm->lba_map);
        free(cm);
    }
}

const char* cache_manager_get_hash(cache_manager_t* cm, long long lba) {
    return (const char*)g_hash_table_lookup(cm->lba_map, &lba);
}

bool cache_manager_read_from_disk(cache_manager_t* cm, const char* hash, void* buffer) {
    char path[1024];
    snprintf(path, sizeof(path), "%s/%s", cm->disk_cache_dir, hash);
    
    FILE* fp = fopen(path, "rb");
    if (!fp) return false;

    fread(buffer, CHUNK_SIZE, 1, fp);
    fclose(fp);
    return true;
}

bool cache_manager_write_to_disk(cache_manager_t* cm, const char* hash, const void* data, size_t size) {
    char path[1024];
    snprintf(path, sizeof(path), "%s/%s", cm->disk_cache_dir, hash);

    FILE* fp = fopen(path, "wb");
    if (!fp) {
        LOG_ERROR("无法写入磁盘缓存: %s", path);
        return false;
    }

    fwrite(data, size, 1, fp);
    fclose(fp);
    return true;
}